package com.cmc.cloud.cmclink.doc.controller.admin;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cmc.cloud.cmclink.doc.api.document.emums.CostTypeEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.ExImTypeEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.SiStatusEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.SiValidEnum;
import com.cmc.cloud.cmclink.doc.constants.UrlConstants;
import com.cmc.cloud.cmclink.doc.entity.BlnoDO;
import com.cmc.cloud.cmclink.doc.mapper.BlnoMapper;
import com.cmc.cloud.cmclink.doc.service.si.*;
import com.cmc.cloud.cmclink.doc.util.CostChargeWithBlnoUtil;
import com.cmc.cloud.cmclink.doc.vo.blnochargevo.BlnoCheckMsgReqVO;
import com.cmc.cloud.cmclink.doc.vo.blnochargevo.BlnoLocalChargeResultVO;
import com.cmc.cloud.cmclink.doc.vo.blnovo.operatevo.BlnoSendArrivalReqVO;
import com.cmc.cloud.cmclink.doc.vo.voyagelock.*;
import com.cmes.framework.biz.advice.annotations.UseResponsePropertyAdvice;
import com.cmes.framework.common.pojo.PageResult;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import com.cmes.framework.common.pojo.CommonResult;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;

import javax.servlet.http.HttpServletResponse;
import javax.validation.*;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 航次锁船记录前端接口Controller
 * 
 * @author codegen
 */
@Tag(name = "管理后台 - 航次锁船记录")
@RestController
@Validated
@RequestMapping(UrlConstants.APPLICATION_URL + "/voyage-lock")
public class VoyageLockController {

    @Resource
    private VoyageLockService voyageLockService;
    @Resource
    private BlnoService blnoService;

    @Resource
    private CostChargeWithBlnoUtil costChargeWithBlnoUtil;
    @Resource
    private BlnoLocalCostImService blnoLocalCostImService;
    @Resource
    private BlnoFreightService blnoFreightService;
    @Resource
    private BlnoLocalChargeService blnoLocalChargeService;
    @Resource
    private BlnoMapper blnoMapper;
    @Resource
    private BlnoArrivalNoticeService blnoArrivalNoticeService;
//
//    @Operation(summary = "创建航次锁船记录")
//	@PostMapping("/create")
//    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:create')")
//    public CommonResult<Void> createVoyageLock(@Valid @RequestBody VoyageLockCreateReqVO createReqVO) {
//        voyageLockService.createVoyageLock(createReqVO);
//        return CommonResult.success();
//    }
//
//    @Operation(summary = "更新航次锁船记录")
//	@PostMapping("/update")
//    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:update')")
//    public CommonResult<Void> updateVoyageLock(@Valid @RequestBody VoyageLockUpdateReqVO updateReqVO) {
//        voyageLockService.updateVoyageLock(updateReqVO);
//        return CommonResult.success();
//    }
//
//    @Operation(summary = "删除航次锁船记录")
//	@PostMapping("/delete/{id}")
//    @Parameter(name = "id", description = "编号", required = true)
//    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:delete')")
//    public CommonResult<Void> deleteVoyageLock(@PathVariable("id") Long id) {
//        voyageLockService.deleteVoyageLock(id);
//        return CommonResult.success();
//    }
//
//    @Operation(summary = "获得航次锁船记录")
//	@GetMapping("/get/{id}")
//    @Parameter(name = "id", description = "编号", required = true, example = "1024")
//    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:query')")
//    public CommonResult<VoyageLockRespVO> getVoyageLock(@PathVariable("id") Long id) {
//        VoyageLockDO voyageLock = voyageLockService.getVoyageLock(id);
//        return CommonResult.success(VoyageLockConvert.INSTANCE.convert(voyageLock));
//    }
//
//    @Operation(summary = "获得航次锁船记录列表")
//	@GetMapping("/list")
//    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
//    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:query')")
//    public CommonResult<List<VoyageLockRespVO>> getVoyageLockList(@RequestParam("ids") Collection<Long> ids) {
//        List<VoyageLockDO> list = voyageLockService.getVoyageLockList(ids);
//        return CommonResult.success(VoyageLockConvert.INSTANCE.convertList(list));
//    }
//
//    @Operation(summary = "获得航次锁船记录分页")
//	@GetMapping("/page")
//    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:query')")
//    public CommonResult<PageResult<VoyageLockRespVO>> getVoyageLockPage(@Valid VoyageLockPageReqVO pageVO) {
//        PageResult<VoyageLockDO> pageResult = voyageLockService.getVoyageLockPage(pageVO);
//        List<VoyageLockRespVO> results = VoyageLockConvert.INSTANCE.convertList(pageResult.getList());
//        return CommonResult.success(new PageResult<>(results,pageResult.getTotal()));
//    }

    @Operation(summary = "获得列表Ex")
    @PostMapping("/listEx")
    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:listEx')")
    @UseResponsePropertyAdvice
    public CommonResult<List<VoyageLockRespVO>> listEx(@Valid @RequestBody VoyageLockReqVO reqVO) {
        List<VoyageLockRespVO> list = voyageLockService.list(reqVO, ExImTypeEnum.EX);
        return CommonResult.success(list);
    }
    /**
     * @param reqVo
     */
    @Operation(summary = "lockChargeEx前 " +
            "1.检查 费用是否已锁定 如锁定 提示：提单号xxxx 费用已锁定，无需再次锁定！" +
            "2.校验费用是否已计算 如存在未计算费用的提单\n" +
            "     * 做出提示：提单号xxxxxxxx、xxxxxxxx无#应收/应付#费用，是否继续锁定？")
    @PostMapping("/lockChargeExCheck")
    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:lock-chargeEx')")
    public CommonResult<BlnoCheckMsgReqVO> lockChargeExCheck(@Valid @RequestBody VoyageLockReqVO reqVo) {
        BlnoCheckMsgReqVO checkMsgReqVO = voyageLockService.lockChargeExCheck(reqVo);
        return CommonResult.success(checkMsgReqVO);
    }
    @Operation(summary = "费用锁 Lock ChargeEx")
    @PostMapping("/lockChargeEx")
    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:lock-chargeEx')")
    public CommonResult<List<BlnoLocalChargeResultVO>> lockChargeEx(@Valid @RequestBody VoyageLockReqVO reqVo) {
        voyageLockService.lockChargeEx(reqVo);
        List<Long> ids = new ArrayList<>();
        List<BlnoDO> blnoDOList = blnoMapper.selectList(
                new LambdaQueryWrapper<BlnoDO>()
                        .eq(BlnoDO::getBkgVesselCode, reqVo.getVesselCode())
                        .eq(BlnoDO::getBkgVoyage, reqVo.getVoyage())
                        .eq(BlnoDO::getPolCode, reqVo.getPortCode())
                        .eq(BlnoDO::getValid, SiValidEnum.VALID.getValue())
                        .in(BlnoDO::getSiStatus, SiStatusEnum.getValidStatus())
        );
        blnoDOList.forEach(blnoDO -> ids.add(blnoDO.getId()));
        //调用接口发送航次下提单未结转的 Freight、Local Charge 、Local Cost 结转到财务，同时记录结转财务人与结转时间
        Map<Long, String> errMsgMap1 = blnoFreightService.toAccountFreight(ids);
        List<BlnoLocalChargeResultVO> rspList1 =
                costChargeWithBlnoUtil.transitMapToList(ids, errMsgMap1, CostTypeEnum.FREIGHT_ACCOUNT.getValue());

        blnoLocalChargeService.toAccount(ExImTypeEnum.EX.getValue(), ids);
        Map<Long, String> errMsgMap3 = blnoLocalCostImService.toAccountLocalCost(ids, ExImTypeEnum.EX.getValue());
        List<BlnoLocalChargeResultVO> rspList3 =
                costChargeWithBlnoUtil.transitMapToList(ids, errMsgMap3, CostTypeEnum.LOCAL_COST_ACCOUNT_EX.getValue());
        rspList1.addAll(rspList3);
        return CommonResult.success(rspList1);
    }
    @Operation(summary = "航次锁 Lock VoyageEx")
    @PostMapping("/lockVoyageEx")
    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:lock-voyageEx')")
    public CommonResult<Void> lockVoyageEx(HttpServletResponse response, @Valid @RequestBody VoyageLockReqVO reqVO) {
        voyageLockService.lockVoyage(response,reqVO, ExImTypeEnum.EX);
        return CommonResult.success();
    }
    @Operation(summary = "获得列表Im")
    @PostMapping("/listIm")
    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:listIm')")
    @UseResponsePropertyAdvice
    public CommonResult<PageResult<VoyageLockImBaseVO>> listIm(@Valid @RequestBody VoyageLockImPageReqVO reqVO) {
        PageResult<VoyageLockImBaseVO> list = voyageLockService.getBlnoLockIm(reqVO);
        return CommonResult.success(list);
    }
    /**
     * @param reqVos
     */
    @Operation(summary = "lockCharge前 " +
            "1.检查 费用是否已锁定 如锁定 提示：提单号xxxx 费用已锁定，无需再次锁定！" +
            "2.校验费用是否已计算 如存在未计算费用的提单\n" +
            "     * 做出提示：提单号xxxxxxxx、xxxxxxxx无#应收/应付#费用，是否继续锁定？")
    @PostMapping("/lockChargeCheck")
    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:lock-chargeIm')")
    public CommonResult<BlnoCheckMsgReqVO> lockChargeCheck(@Valid @RequestBody List<VoyageLockImReqVO> reqVos) {
        BlnoCheckMsgReqVO checkMsgReqVO = voyageLockService.lockChargeCheck(reqVos);
        return CommonResult.success(checkMsgReqVO);
    }
    @Operation(summary = "费用锁 Lock ChargeIm")
    @PostMapping("/lockChargeIm")
    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:lock-chargeIm')")
    public CommonResult<Void> lockChargeIm(@Valid @RequestBody List<VoyageLockImReqVO> reqVos) {
        voyageLockService.lockChargeIm(reqVos);
        List<Long> blnoIds=new ArrayList<>();
        if (!reqVos.isEmpty()) {
            for (VoyageLockImReqVO reqVo : reqVos) {
                List<Long> split = Arrays.stream(reqVo.getBlnoIds().split(",")).map(Long::parseLong).collect(Collectors.toList());
                //再次验证 使用ids加速查询
                List<Long> collect = blnoMapper.selectBatchIds(split).stream().map(BlnoDO::getId).collect(Collectors.toList());
                if (!collect.isEmpty()) {
                    blnoIds.addAll( collect);
                }
            }
            //调用接口发送航次下提单未结转的 Freight、Local Charge 、Local Cost 结转到财务，同时记录结转财务人与结转时间
            Map<Long, String> errMsgMap1 = blnoFreightService.toAccountFreight(blnoIds);
            List<BlnoLocalChargeResultVO> rspList1 =
                    costChargeWithBlnoUtil.transitMapToList(blnoIds, errMsgMap1, CostTypeEnum.FREIGHT_ACCOUNT.getValue());

            blnoLocalChargeService.toAccount(ExImTypeEnum.IM.getValue(), blnoIds);
            Map<Long, String> errMsgMap3 = blnoLocalCostImService.toAccountLocalCost(blnoIds, ExImTypeEnum.IM.getValue());
            List<BlnoLocalChargeResultVO> rspList3 =
                    costChargeWithBlnoUtil.transitMapToList(blnoIds, errMsgMap3, CostTypeEnum.LOCAL_COST_ACCOUNT_IM.getValue());
            rspList1.addAll(rspList3);
        }
        return CommonResult.success();
    }
    /**
     * lockDO
     *
     * @param reqVos
     */
    @Operation(summary = "lockDO")
    @PostMapping("/lockDO")
    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:lockDO')")
    public CommonResult<Void> lockDO(@Valid @RequestBody List<VoyageLockImReqVO> reqVos) {
        blnoService.lockDO(reqVos);
        return CommonResult.success();
    }
    /**
     * unLockDO
     * @param reqVos
     */
    @Operation(summary = "unLockDO")
    @PostMapping("/unLockDO")
    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:unLockDO')")
    public CommonResult<Void> unLockDO(@Valid @RequestBody List<VoyageLockImReqVO> reqVos) {
        blnoService.unLockDO(reqVos);
        return CommonResult.success();
    }
    /**
     * setSendArriveNotice
     *
     * @param reqVos
     */
    @Operation(summary = "setSendArriveNotice")
    @PostMapping("/setSendArriveNotice")
    @PreAuthorize("@ss.hasPermission('doc:voyage-lock:setSendArriveNotice')")
    public CommonResult<Void> setSendArriveNotice(@Valid @RequestBody List<VoyageLockImReqVO> reqVos) {
        List<Long> blnoIds=new ArrayList<>();

        if (!reqVos.isEmpty()) {
            String currentPort = reqVos.get(0).getPortCode();
            for (VoyageLockImReqVO reqVo : reqVos) {
                List<Long> split = Arrays.stream(reqVo.getBlnoIds().split(",")).map(Long::parseLong).collect(Collectors.toList());

                //再次验证 使用ids加速查询
                List<Long> collect = blnoMapper.selectBatchIds(split).stream().map(BlnoDO::getId).collect(Collectors.toList());
                if (!collect.isEmpty()) {
                    blnoIds.addAll( collect);
                }

            }

            BlnoSendArrivalReqVO reqVO = new BlnoSendArrivalReqVO(blnoIds, currentPort);
            blnoArrivalNoticeService.sendArrivalNotice(reqVO);
        }

        return CommonResult.success();
    }
}
